<!-- 海康播放器 -->

<template>
  <div ref="player" :id="id" :class="className" />
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import H5Player from '../H5Player'
import CONST from './CONST'
import props from './props'

let ENCRYPT // 加密工具
let HIK_CONFIG // 海康配置

// ============================== 导出组件 ============================== //

export default CORE.extend(H5Player, {
  /**
   * 名称定义 (实际使用名称)
   */
  name: 'HkPlayer',

  /**
   * 属性注册 (抽取以便查阅)
   */
  props: {
    ...H5Player.props,
    ...props,
  },

  /**
   * 状态数据
   */
  data() {
    return {
      ...H5Player.data.call(this),

      tryCount: 0, // 重试次数
      wndId: 1, // 当前视频
      wndNum: 1, // 窗口数量
      layout: '1x1', // 布局 (1x1、2x2、3x3、1+5 等)
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    ...H5Player.computed,

    /**
     * 开始参数
     */
    startParam() {
      const { wndId, replay, value, replayTime, beforeSecond, afterSecond } = this
      if (replay) {
        const s = 1000
        const startTimeStamp = replayTime ? replayTime - beforeSecond * s : CORE.timeNum(CORE.today())
        const endTimeStamp = replayTime ? replayTime + afterSecond * s : CORE.timeNum(CORE.today(1), -1)
        const argument = JSON.stringify({
          ...CONST.PLAYBACK_CONFIG,
          cameraIndexCode: value,
          wndId,
          startTimeStamp: startTimeStamp / s | 0, // 开始时间，单位：秒
          endTimeStamp: endTimeStamp / s | 0, // 结束时间，单位：秒
        })
        return { funcName: 'startPlayback', argument }
      } else {
        const argument = JSON.stringify({
          ...CONST.PREVIEW_CONFIG,
          cameraIndexCode: value,
          wndId,
        })
        return { funcName: 'startPreview', argument }
      }
    },

    /**
     * 停止参数
     */
    stopParam() {
      const { wndId } = this
      const argument = JSON.stringify({ list: [{ wndId }] })
      return { funcName: 'stopMultiPlay', argument }
    },
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    ...H5Player.methods,

    /**
     * 加载
     */
    async load() {
      const { layout, buttonIDs } = this

      await CORE.loadJS(CONST.JQUERY, CONST.NAME)
      await CORE.loadJS(CONST.JSENCRYPT, CONST.NAME)
      await CORE.loadJS(CONST.JS_WEB_CONTROL, CONST.NAME)

      if (!HIK_CONFIG) {
        HIK_CONFIG = await CORE.loadJSON(CORE.asset('HIK_CONFIG.json'))
        const config = buttonIDs === null ? { layout } : { layout, buttonIDs }
        CORE.merge(CONST.INIT_CONFIG, HIK_CONFIG, config)
      }

      // 连接海康插件
      this.player = new window.WebControl({
        ...CONST.NEW_CONTROL,
        szPluginContainer: this.id,
        cbConnectSuccess: this.connectSuccess,
        cbConnectError: this.connectError,
        cbConnectClose: this.connectCloded,
      })
    },

    /**
     * 开始
     */
    start() {
      const { player } = this
      if (player) {
        player.JS_RequestInterface(this.startParam) // 开始播放
      }
    },

    /**
     * 停止
     */
    stop() {
      const { player } = this
      if (player) {
        player.JS_RequestInterface(this.stopOption) // 停止播放
      }
    },

    /**
     * 显示
     */
    show() {
      this.player.JS_ShowWnd() // 显示窗口
    },

    /**
     * 隐藏
     */
    hide() {
      this.player.JS_HideWnd() // 隐藏窗口
    },

    /**
     * 销毁
     */
    distroy() {
      const { player } = this
      if (player) {
        player.JS_HideWnd() // 隐藏窗口
        player.JS_Disconnect() // 断开连接
        this.player = null
      }
      window.removeEventListener('resize', this.resize)
      window.removeEventListener('scroll', this.resize)
    },

    /**
     * 连接成功
     */
    async connectSuccess() {
      const { player } = this

      // 启动服务
      await player.JS_StartService('window', CONST.START_SERVICE)

      // 创建窗口
      await player.JS_CreateWnd(this.id)

      // 设置控件回调
      await player.JS_SetWindowControlCallback({ cbIntegrationCallBack: this.setCallback })

      // 设置加密工具
      await this.setPubKey()

      // 设置初始化
      await this.setInit()

      // 设置调整尺寸
      this.resize()
      window.addEventListener('resize', this.resize)
      window.addEventListener('scroll', this.resize)

      // 标记加载完成
      this.loaded = true
    },

    /**
     * 连接失败
     */
    connectError() {
      // 程序未启动时执行error函数，采用wakeup来启动程序
      window.WebControl.JS_WakeUp('VideoWebPlugin://')
      this.player = null
      this.tryCount++

      // 设置提示和重试
      const { player } = this.$refs
      player.innerHTML = CONST.TIP
      if (this.tryCount < 2) setTimeout(this.load, 2000)
      else player.innerHTML = CONST.LINK
    },

    /**
     * 连接关闭
     */
    connectCloded(isNormalClose) { // 异常断开 false 正常断开 true
      if (!isNormalClose) this.load()
    },

    /**
     * 设置控件回调
     */
    async setCallback({ responseMsg }) {
      const { type, msg } = responseMsg
      if (type === 1 || type === 2) { // 1 点击窗口, 2 开始播放
        this.wndId = msg.wndId
      } else if (type === 6) { // 6 切换布局
        this.wndNum = msg.wndNum
        this.layout = msg.layout
      } else {
        CORE.logInfo('插件回调', type, msg) // 3 抓图结果，4 预览紧急录相， 5 全屏事件，7 窗口双击
      }
      this.$emit('change', responseMsg) // 触发事件
    },

    /**
     * 设置加密工具
     */
    async setPubKey() {
      const { player } = this
      const resp = await player.JS_RequestInterface({
        funcName: 'getRSAPubKey',
        argument: JSON.stringify({ keyLength: 1024 }),
      })

      ENCRYPT = new window.JSEncrypt() // 加密工具
      ENCRYPT.setPublicKey(resp.responseMsg.data)
    },

    /**
     * 设置初始化
     */
    async setInit() {
      const { player } = this
      const secret = ENCRYPT.encrypt(CONST.INIT_CONFIG.secret)
      const playMode = this.replay ? 1 : 0
      const argument = JSON.stringify({ ...CONST.INIT_CONFIG, secret, playMode })

      await player.JS_RequestInterface({ funcName: 'init', argument }) // 初始化
    },

    /**
     * 调整尺寸
     */
    resize() {
      const { player } = this
      const refDiv = this.$refs.player
      refDiv && player.JS_Resize(refDiv.clientWidth, refDiv.clientHeight)
    },
  },
})
</script>
